/*****************************************************************************
 * Copyright (C) Stacy Curl. All rights reserved.                            *
 * ------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the BSD      *
 * style license a copy of which has been included with this distribution in *
 * the LICENSE.txt file.                                                     *
 *****************************************************************************/
package picounit.features.mocking;

import picounit.PicoUnitException;
import picounit.mocker.Action;
import picounit.mocker.OccurencesMatcher;
import picounit.mocker.SetConsequenceCapturer;
import picounit.mocker.SetConsequenceMatcher;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

@SuppressWarnings("unchecked")
class CombinedSetConsequenceMatcher extends BaseConsequenceMatcher
	implements SetConsequenceMatcher, SetConsequenceCapturer {

	public CombinedSetConsequenceMatcher(ActiveRecordingPlaybackMock activeRecordingPlaybackMock,
		OccurencesMatcher occurencesMatcher, MockInvocationInspector mockInvocationInspector) {

		super(activeRecordingPlaybackMock, occurencesMatcher, mockInvocationInspector);
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	// SetConsequenceMatcher methods
	///////////////////////////////////////////////////////////////////////////////////////////////
	
	public OccurencesMatcher andReturn(Set result) {
		return will(returnValue(result));
	}

	@SuppressWarnings("unchecked")
	public OccurencesMatcher andReturn(Object ... results) {
		Set<Object> set = createType(Set.class);

		Set repeatedElements = Collections.EMPTY_SET;

		for (Object result : results) {
			if (set.contains(result)) {
				if (repeatedElements == Collections.EMPTY_SET) {
					repeatedElements = new HashSet();
				}
				
				repeatedElements.add(result);
			}
			else {
				set.add(result);
			}
		}

		if (repeatedElements != Collections.EMPTY_SET) {
			throw new PicoUnitException("Repeated elements found: " + repeatedElements);
		}

		return will(returnValue(set));
	}

	public OccurencesMatcher andPerform(Action action) {
		return will(new ActionStub(action));
	}
	
	///////////////////////////////////////////////////////////////////////////////////////////////
	// SetConsequenceCapturer methods
	///////////////////////////////////////////////////////////////////////////////////////////////
	
	public OccurencesMatcher andReturning(Set result) {
		return andReturn(result);
	}
	
	public OccurencesMatcher andReturning(Object ... results) {
		return andReturn(results);
	}

	public OccurencesMatcher andPerforming(Action action) {
		return andPerform(action);
	}

	public void andRaising(Throwable throwable) {
		andRaise(throwable);
	}
}
